package ocean

import (
	"cid-media-api/global"
	"cid-media-api/internal/adcore"
	. "cid-media-api/models/batch"
	"context"
	"encoding/json"
	"fmt"
	. "github.com/oceanengine/ad_open_sdk_go/models"
	"golang.org/x/time/rate"
	"regexp"
	"strconv"
	"sync"
	"time"
)

type OceanAdapter struct {
	client      *OceanClient
	rateLimiter *rate.Limiter
}

func NewOceanAdapter(AdvertiserID int64, AccessToken string) *OceanAdapter {
	return &OceanAdapter{
		client:      NewOceanClient(AccessToken, AdvertiserID),
		rateLimiter: rate.NewLimiter(rate.Every(1000/30*time.Millisecond), 5), // 限流器（示例：1000/30 毫秒/次，最多5次）
	}
}

func (a *OceanAdapter) BatchCreate(ctx context.Context, req adcore.BatchRequest) (adcore.BatchResult, error) {
	result := adcore.BatchResult{}
	var wg sync.WaitGroup
	errChan := make(chan error, 1)
	mu := sync.Mutex{}

	// 初始化服务
	projectService := NewProjectService(a.client, a.rateLimiter)
	promotionService := NewPromotionService(a.client, a.rateLimiter)

	audiencePackageIDJson := req.AdGroup.Template.(BatchProjectTemplate).AudiencePackages

	var audiencePackageIDs []int64
	err := json.Unmarshal([]byte(audiencePackageIDJson), &audiencePackageIDs)
	if err != nil {
		return result, err
	}
	projectTemplate := req.AdGroup.Template.(BatchProjectTemplate)
	// 解析 DeliverySettings 只做一次
	var PrjReq ProjectCreateV30Request

	// 解析 DeliverySettings
	deliverySettingsJson, err := json.Marshal(projectTemplate.DeliverySettings)
	if err != nil {
		return result, fmt.Errorf("解析 DeliverySettings 失败: %w", err)
	}
	// 转换为字符串
	deliverySettingsStr := string(deliverySettingsJson)

	// 转换为 ProjectCreateV30Request
	err = json.Unmarshal([]byte(deliverySettingsStr), &PrjReq)
	if err != nil {
		return result, fmt.Errorf("解析 DeliverySettings 失败: %w", err)
	}

	for index, audiencePackageID := range audiencePackageIDs {
		// 创建定向包 TODO: 定向包暂时不单独创建，后续考虑是否单独创建

		// 获取本地定向包模板
		var batchAudiencePackage BatchAudiencePackage
		global.CidDb.
			Model(&BatchAudiencePackage{}).
			Where("id =?", audiencePackageID).
			Where("status", 1).
			First(&batchAudiencePackage)

		// 解析定向信息并添加进项目模板
		err = json.Unmarshal([]byte(batchAudiencePackage.AudienceInfo), PrjReq.Audience)

		if err != nil {
			return result, err
		}
		projectTemplate.DeliverySettings = PrjReq
		// 协调创建流程
		wg.Add(1) // 增加 WaitGroup 计数
		go func() {
			defer wg.Done() // 协程结束时减少 WaitGroup 计数

			adGroupParams := adcore.AdGroupParams{
				Name:     parseProjectName(projectTemplate, index), // 根据模板解析生成项目名称
				Template: projectTemplate,
			}

			projectID, err := projectService.BatchCreate(ctx, adGroupParams)
			if err != nil {
				errChan <- err
				return
			}

			// 项目创建成功后触发广告创建
			adTemplate := req.Ad.Template.(BatchPromotionTemplate)
			promotionID, err := promotionService.BatchCreate(ctx, adcore.AdParams{
				Template:  adTemplate,
				AdGroupID: *projectID,
			})
			if err != nil {
				errChan <- err
				return
			}

			mu.Lock()
			result.AdIDs = append(result.AdIDs, strconv.FormatInt(*promotionID, 10))
			mu.Unlock()
		}()
	}

	// 等待所有协程完成
	go func() {
		wg.Wait()
		close(errChan)
	}()

	// 检查错误通道
	for err := range errChan {
		if err != nil {
			return result, err
		}
	}

	return result, nil
}

// 解析项目名称模板
func parseProjectName(projectTemplate BatchProjectTemplate, index int) string {
	reg := regexp.MustCompile(`{(\w+)}`)
	result := reg.ReplaceAllStringFunc(projectTemplate.ProjectName, func(s string) string {
		switch s[1 : len(s)-1] {
		case incrementId:
			return strconv.Itoa(projectTemplate.AutoIncrementID + index)
		case date:
			return time.Now().Format(time.DateOnly)
		case datetime:
			return time.Now().Format(time.DateTime)
		case dateMd:
			return time.Now().Format("01-02")
		default:
			return s
		}
	})

	if projectTemplate.SystemIdSuffix > 0 {
		result += "-" + systemId
	}

	return result
}

const (
	incrementId = "自增序号"
	date        = "日期"
	datetime    = "日期时间"
	dateMd      = "月日"
	systemId    = "悦投CID"
)
